package com.harvey.study.data.structure.datastructure.game;

import java.util.Random;
import java.util.Scanner;
import com.harvey.study.data.structure.datastructure.linkedlist.SingledLinkedListV2;

/**
 * date: 2021-04-25
 * desc: “21点”纸牌游戏是一种古老的扑克牌游戏，
 * 游戏规则是参与者设法使自己的牌达到总分21，
 * 而不超过这个数值。扑克牌的分值取它们的面值，
 * A充当1分，J、Q和K分别是11、12和13分。
 * 
 * 庄家和玩家，在开局时各有两张牌，玩家可以看到自己的牌及总分，
 * 而庄家有一张牌暂时是隐藏的。接下来，只要愿意，玩家可以再拿一张牌，
 * 如果玩家的总分超过了21，即“引爆”，那玩家就输了。在玩家拿了额外的牌后，
 * 庄家将显示隐藏的牌。只要庄家的总分小于等于21，那么他就必须拿牌。
 * 如果庄家引爆了，那么玩家将获胜。否则将玩家和庄家的总分比较，
 * 如果玩家的总分大于庄家的总分，则玩家获胜。如果二者的总分相同，
 * 则玩家与庄家打成平局。
 * 
 * 利用链表实现洗牌、发牌、计算总分、显示扑克牌的花色和面值。
 */
public class TwentyOneScore {
    private SingledLinkedListV2<Integer> poker = new SingledLinkedListV2<Integer>(); 

    private Integer playerGoldCount = 100;
    private Integer bannerGoldCount = 100;


    private int index ;//下标

    public TwentyOneScore(){
        for(int i=1;i<=4;i++){
            for(int j=1;j<=13;j++){
                poker.add(j);
            }
        }
    }

    /**
     * 洗牌
     * 随即一定次数，调整链表位置
     */
    public void shuffle(){
        index=0;
        int count = 500;
        for(int i=0;i<count;i++){
            Random random = new Random();
            int flag = random.nextInt(52)+1;
            poker.add(poker.remove(flag));
        }
    }

    /**
     * 按顺序获取一张牌
     * @return
     */
    public Integer getOneCard(){
        return poker.find(++index);
    }

    public void playerSubtract(){
        playerGoldCount-=10;
        bannerGoldCount+=10;
        if(playerGoldCount<0){
            playerGoldCount=0;
        }
    }

    public void bannerSubtract(){
        bannerGoldCount-=10;
        playerGoldCount+=10;
        if(bannerGoldCount<0){
            bannerGoldCount=0;
        }
    }


    /**
     * 庄家和玩家，在开局时各有两张牌，玩家可以看到自己的牌及总分，
     * 而庄家有一张牌暂时是隐藏的。接下来，只要愿意，玩家可以再拿一张牌，
     * 如果玩家的总分超过了21，即“引爆”，那玩家就输了。在玩家拿了额外的牌后，
     * 庄家将显示隐藏的牌。只要庄家的总分小于等于21，那么他就必须拿牌。
     * 如果庄家引爆了，那么玩家将获胜。否则将玩家和庄家的总分比较，
     * 如果玩家的总分大于庄家的总分，则玩家获胜。如果二者的总分相同，
     * 则玩家与庄家打成平局。
     */
    public void start(){
        //洗牌
        shuffle();

        //庄家
        User banker = new User();

        //玩家
        User player = new User();

        //初始化牌，每人两张
        for(int i=0;i<2;i++){
            banker.receiveCard(getOneCard());
            player.receiveCard(getOneCard());
        }

        System.out.println("发牌完毕，查看自己的牌");
        System.out.print("玩家的牌:");
        player.showCard();
        System.out.println();
        System.out.print("庄家的牌:");
        banker.noShowFirstCard();
        System.out.println();


        while (true){
            Scanner playerScanner = new Scanner(System.in);
            System.out.println("玩家是否要牌 1要 2不要");
            Integer continueDeal = 1;
            if (playerScanner.hasNextLine()) {
                continueDeal = Integer.valueOf(playerScanner.nextLine());
            }
            if(continueDeal==1){
                player.receiveCard(getOneCard());
                System.out.print("玩家的牌:");
                player.showCard();
                System.out.println();

                if(!player.checkScore()){
                    System.out.println("玩家总点数："+player.getTotalScore()+",大于21点，玩家输了");
                    playerSubtract();
                    break;
                }

                System.out.print("庄家的牌:");
                banker.showCard();


                if(banker.checkScore()){
                    System.out.println("庄家小于21点，继续拿牌");
                    banker.receiveCard(getOneCard());
                    System.out.print("庄家的牌:");
                    banker.showCard();
                    System.out.println();
                }

                if(!banker.checkScore()){
                    System.out.println("庄家总点数："+banker.getTotalScore()+",大于21点，玩家获胜");
                    bannerSubtract();
                    break;
                }else{
                    System.out.println("庄家总点数："+banker.getTotalScore());
                    System.out.println("玩家总点数："+player.getTotalScore());
                    if(player.getTotalScore()>21 || banker.getTotalScore() >= player.getTotalScore()){
                        System.out.println("庄家获胜");
                        playerSubtract();
                    }else{
                        System.out.println("玩家获胜");
                        bannerSubtract();

                    }
                    break;
                }
            }else{
                System.out.print("庄家的牌:");
                banker.showCard();
                System.out.println();

                System.out.println("庄家总点数："+banker.getTotalScore());
                System.out.println("玩家总点数："+player.getTotalScore());
                if(player.getTotalScore()>21 || 
                        (banker.getTotalScore()<=21 && banker.getTotalScore() >= player.getTotalScore())){
                    System.out.println("庄家获胜");
                    playerSubtract();
                }else{
                    System.out.println("玩家获胜");
                    bannerSubtract();
                }
                break;
            }
        }

    }


    public static void main(String[] args) {
        TwentyOneScore twentyOneScore = new TwentyOneScore();

        int index = 1;
        while(true){
            twentyOneScore.start();
            System.out.println("统计第"+index+"局结束庄家，玩家金币情况");
            System.out.println("庄家："+twentyOneScore.bannerGoldCount);
            System.out.println("玩家："+twentyOneScore.playerGoldCount);

            if(twentyOneScore.bannerGoldCount==0){
                System.out.println("庄家输光了，游戏结束");
                break;
            }else if(twentyOneScore.playerGoldCount==0){
                System.out.println("玩家输光了，游戏结束");
                break;
            }
            index++;

            System.out.println();
            System.out.println();
            System.out.println();

        }


    }

}
